package com.example.springbootdemo.config.typehandler;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.PrecisionModel;
import com.vividsolutions.jts.io.WKBReader;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 自定义映射MySQL中geometry类型到Geometry
 *
 * @author xuwangqi on 2020/11/17
 */
/*
 * mybatis查询结果集中 mysql的geometry类型映射到Geometry对象
 * 其中 setParameter 方法用于把 java 对象设置到 PreparedStatement 的参数中，
 * getResult 方法用于从 ResultSet（根据列名或者索引位置获取） 或 CallableStatement（根据存储过程获取） 中取出数据转换为 java 对象。
 */
@MappedTypes(value = {Geometry.class})
public class MysqlGeometryTypeHandler extends BaseTypeHandler<Geometry> {

    private WKBReader _wkbReader;
    private int _srid = 0;
    public MysqlGeometryTypeHandler() {
        GeometryFactory _geometryFactory = new GeometryFactory(new PrecisionModel(), _srid);
        _wkbReader = new WKBReader(_geometryFactory);
    }
    public MysqlGeometryTypeHandler(int srid) {
        GeometryFactory _geometryFactory = new GeometryFactory(new PrecisionModel(), srid);
        _wkbReader = new WKBReader(_geometryFactory);
    }

    @Override
    public Geometry getNullableResult(ResultSet arg0, String arg1) throws SQLException {
        return fromMysqlWkb(arg0.getBytes(arg1));
    }

    @Override
    public Geometry getNullableResult(ResultSet arg0, int arg1) throws SQLException {
        return fromMysqlWkb(arg0.getBytes(arg1));
    }
   //从存储过程中获得
    @Override
    public Geometry getNullableResult(CallableStatement arg0, int arg1) throws SQLException {
        return fromMysqlWkb(arg0.getBytes(arg1));
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Geometry geometry, JdbcType jdbcType)
            throws SQLException {
        //插入和修改时设置geometry类型值
        ps.setString(i,geometry.toString());
    }

    /*
     * bytes转Geometry对象
     */
    private Geometry fromMysqlWkb(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        try {
            byte[] geomBytes = ByteBuffer.allocate(bytes.length - 4).order(ByteOrder.LITTLE_ENDIAN)
                    .put(bytes, 4, bytes.length - 4).array();
            Geometry geometry = _wkbReader.read(geomBytes);
            return geometry;
        } catch (Exception e) {
        }
        return null;
    }
}

